package com.iamteer.b_pool;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;

public class MyPool {
	private int init_count = 3;		// 初始化连接数量
	private int max_count = 6;		// 最大连接数量
	private int current_count = 0;	// 记录当前使用连接数
	// 连接池（存放所有的初始化连接）
	private LinkedList<Connection> pool = new LinkedList<Connection>();
	
	// 1. 构造函数中，初始化连接放入连接池
	public MyPool() {
		for (int i = 0; i < init_count; i++) {
			current_count++;
			// 把连接加入连接池
			pool.addLast(createConnection());
		}
	}
	
	// 2. 创建一个新的连接的方法
	public Connection createConnection() {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			// 原始的目标对象
			Connection con = DriverManager.getConnection("jdbc:mysql:///jdbc_demo", "root", "123456");
			// 对 con 创建代理对象
			Connection proxy = (Connection) Proxy.newProxyInstance(
					con.getClass().getClassLoader(),	// 类加载器
					new Class[]{Connection.class},		// 目标对象实现的接口
					new InvocationHandler() {			// 当调用 con 对象方法的时候，自动触发事务处理器
						
						@Override
						public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
							// 方法返回值
							Object result = null;
							// 当前执行的方法的方法名
							String methodName = method.getName();
							// 判断执行了 close 方法的时候，把连接放入连接池
							if ("close".equals(methodName)) {
								System.out.println("Close...");
								pool.addLast(con);
							} else {
								// 调用目标对象方法
								result = method.invoke(con, args);
							}
							return result;
						}
					});
			return proxy;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	// 3. 获取连接
	public Connection getConnection() {
		// 3.1 判断连接池中是否有连接，如果有，直接从连接池取出
		if (pool.size() > 0) {
			return pool.removeFirst();
		}
		
		// 3.2 如果连接池中没有连接，判断是否达到最大连接数，如果没有，则创建
		if (current_count < max_count) {
			// 记录当前使用的连接数
			current_count++;
			// 创建连接
			return createConnection();
		}
		// 3.3 如果已经达到最大连接数，抛出异常
		throw new RuntimeException("当前连接已经达到最大连接数目！");
	}
	
	// 4. 释放连接
	public void releaseConnection(Connection con) {
		// 4.1 判断：如果连接池中的数目小于初始化连接，则放入池中
		if (pool.size() < init_count) {
			pool.addLast(con);
		} else {
			// 4.2 否则，关闭
			try {
				current_count--;
				con.close();
			} catch (SQLException e) {
				throw new RuntimeException(e);
			}
		}
	}

	
	public static void main(String[] args) throws Exception {
		MyPool pool = new MyPool();
		System.out.println("当前连接：" + pool.current_count);
		
		pool.getConnection();
		pool.getConnection();
		pool.getConnection();
		pool.getConnection();
		pool.getConnection();
		Connection con = pool.getConnection();
		// 释放连接
//		pool.releaseConnection(con);
		// 如果直接关闭，则会出错，使用动态代理解决该问题
		 con.close();
		// 再获取
		pool.getConnection();
		System.out.println("连接池：" + pool.pool.size());
		System.out.println("当前连接：" + pool.current_count);
	}
}
